package models

import (
	"github.com/beego/beego/v2/client/orm"
	"github.com/beego/beego/v2/core/logs"
	"personal-skill/lib"
	"time"
)

const (
	TableName               = "t_user"
	IdColumnName            = "id"
	UsernameColumnName      = "username"
	PasswordColumnName      = "password"
	LastLoginTimeColumnName = "last_login_time"
	CreateTimeColumnName    = "create_time"
	UpdateTimeColumnName    = "update_time"
	IsDeleteColumnName      = "is_delete"
)

//func init() {
//	orm.RegisterModel(new(User))
//}

// User 用户
type User struct {
	Id            int64     `json:"id"`
	Username      string    `json:"username"`
	Password      string    `json:"password"`
	LastLoginTime time.Time `json:"lastLoginTime" orm:"null"`
	CreateTime    time.Time `orm:"auto_now_add;null" json:"createTime"`
	UpdateTime    time.Time `orm:"auto_now;null" json:"updateTime"`
	IsDelete      bool      `orm:"column(is_delete);default(0)" json:"-"`
	Menus         []*Menu   `orm:"reverse(many)" json:"-"`
	Role          *Role     `orm:"rel(fk)"`
	//Skills        []*Skill  `orm:"reverse(many)"`
}

func (user *User) TableName() string {
	return TableName
}

type UserPageResp struct {
	Id            int64    `json:"id"`
	Username      string   `json:"username"`
	RoleName      string   `json:"roleName"`
	LastLoginTime lib.Time `json:"lastLoginTime"`
	CreateTime    lib.Time `json:"createTime"`
	UpdateTime    lib.Time `json:"updateTime"`
}

type UserAddParams struct {
	Username string   `json:"username"`
	Password string   `json:"password"`
	Menus    []string `json:"menus"`
	RoleNo   string   `json:"roleNo"`
}

func NewUser() *User {
	return &User{}
}

func (user *User) Del() error {
	if user.Id < 1 {
		return nil
	}
	o := orm.NewOrm()
	_, err := o.QueryTable(user).Filter(IdColumnName, user.Id).Delete()
	return err
}

// DelLogic 逻辑删除
func (user *User) DelLogic() error {
	if user.Id < 1 {
		return nil
	}
	o := orm.NewOrm()
	_, err := o.QueryTable(user).Filter(IdColumnName, user.Id).Update(orm.Params{
		"is_delete": 1,
	})
	return err
}

func (user *User) Save() (int64, error) {
	o := orm.NewOrm()
	insertNum, err := o.Insert(user)
	m2m := o.QueryM2M(user, "Menus")
	for _, menu := range user.Menus {
		_, err := m2m.Add(menu)
		if err != nil {
			logs.Error(err)
		}
	}
	return insertNum, err
}

func (user *User) Update() (int64, error) {
	o := orm.NewOrm()
	return o.Update(user, UsernameColumnName, IsDeleteColumnName)
}

func (user *User) UpdateLastLoginTime() (int64, error) {
	if user.Id < 1 {
		return 0, nil
	}
	user.LastLoginTime = time.Now()
	o := orm.NewOrm()
	return o.Update(user, LastLoginTimeColumnName)
}

func (user *User) GetById() error {
	if user.Id < 1 {
		return nil
	}
	o := orm.NewOrm()
	return o.QueryTable(TableName).
		Filter(IdColumnName, user.Id).
		Filter(IsDeleteColumnName, 0).
		RelatedSel().
		One(user, IdColumnName, UsernameColumnName, LastLoginTimeColumnName, CreateTimeColumnName, UpdateTimeColumnName)
}

func (user *User) GetByPwdAndUsername(pwd string, uname string) error {
	o := orm.NewOrm()
	return o.QueryTable(TableName).
		Filter(PasswordColumnName, pwd).
		Filter(UsernameColumnName, uname).
		Filter(IsDeleteColumnName, 0).
		One(user, IdColumnName, UsernameColumnName, LastLoginTimeColumnName, CreateTimeColumnName, UpdateTimeColumnName)
}

func (user *User) GetByUserName(username string) (*User, error) {
	o := orm.NewOrm()
	res := User{}
	err := o.QueryTable(TableName).
		Filter(UsernameColumnName, username).
		Filter(IsDeleteColumnName, 0).
		One(&res, IdColumnName, UsernameColumnName, LastLoginTimeColumnName, CreateTimeColumnName, UpdateTimeColumnName)
	return &res, err
}

func (user *User) PageList(pageIndex int, pageSize int) ([]UserPageResp, int64, error) {
	var temp []*User
	var res []UserPageResp
	o := orm.NewOrm()
	filter := o.QueryTable(TableName).Filter("is_delete", 0)
	if user.Username != "" {
		filter = filter.Filter("username__icontains", user.Username)
	}
	count, err := filter.Count()
	if count > 0 {
		_, err = filter.
			RelatedSel("Role").
			Limit(pageSize, pageSize*(pageIndex-1)).
			All(&temp, IdColumnName, UsernameColumnName, LastLoginTimeColumnName, CreateTimeColumnName, UpdateTimeColumnName)
		for _, u := range temp {
			res = append(res, UserPageResp{
				Id:            u.Id,
				Username:      u.Username,
				RoleName:      u.Role.RoleName,
				LastLoginTime: lib.TranslateTimeFrom(u.LastLoginTime),
				CreateTime:    lib.TranslateTimeFrom(u.CreateTime),
				UpdateTime:    lib.TranslateTimeFrom(u.UpdateTime),
			})
		}
	}
	return res, count, err
}

func (user *User) GetMenuList() []*Menu {
	o := orm.NewOrm()
	if user.Id > 0 {
		_, _ = o.LoadRelated(user, "Menus")
	}
	return user.Menus
}

func (user *User) GetSkillList() []*Skill {
	var res []*Skill
	o := orm.NewOrm()
	_, _ = o.QueryTable("t_skill").Filter("User", 1).RelatedSel().All(&res)
	return res
}
